package com.bestcem.xm.member.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.bestcem.bp.grpc.v1.base.Page;
import com.bestcem.bp.xm.user.grpc.v1.services.*;
import com.bestcem.xm.common.core.constant.GrpcClientNames;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.uitls.DateUtil;
import com.bestcem.xm.label.constant.Constants;
import com.bestcem.xm.member.dao.MemberUserGroupDao;
import com.bestcem.xm.member.entity.pojo.MemberUserGroupDO;
import com.bestcem.xm.member.enums.MemberStoreStatusEnum;
import com.bestcem.xm.member.service.MemberUserGroupService;
import io.grpc.StatusRuntimeException;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 联系人组织层级服务
 *
 * @author dc.wang <dc.wang@idiaoyan.com>
 * @version V1.0
 * @date 2022/2/16 16:13
 */
@Slf4j
@Component
public class MemberUserGroupServiceImpl implements MemberUserGroupService {

    @GrpcClient(GrpcClientNames.DS_USER)
    private UserGroupServiceGrpc.UserGroupServiceBlockingStub userGroupServiceBlockingStub;

    @Resource
    private MemberUserGroupDao memberUserGroupDao;

    @NotNull
    @Override
    public ServiceResult<Collection<String>> userGroupIds(String userId) {
        if (!StringUtils.hasText(userId)) {
            if (log.isErrorEnabled()) {
                log.error("用户id不存在:{}", userId);
            }
            return ServiceResult.fail("用户id不存在");
        }
        // 查询用户组织层级
        ServiceResult<List<Group>> groupResult = this.userStores(userId);
        if (!groupResult.isSuccess()) {
            if (log.isErrorEnabled()) {
                log.error("查询用户组织层级失败({}):{}", userId, groupResult);
            }
            return ServiceResult.fail("查询用户组织层级失败");
        }

        return ServiceResult.success(groupResult.getData().stream().map(Group::getId).collect(Collectors.toList()));
    }

    @Override
    public ServiceResult<String> flush(String orgId) {
        if (log.isInfoEnabled()) {
            log.info("开始同步组织层级信息：{}", orgId);
        }
        int totalCount = 0;
        for (int i = 0; ; i++) {
            // 查询组织企业组织层级
            ListGroupsByOrgIdRequest.Builder builder = ListGroupsByOrgIdRequest.newBuilder();
            builder.setOrgId(orgId);
            builder.setPaging(true);
            Page pageParam = Page.newBuilder().setPage(i).setSize(com.bestcem.xm.member.constant.Constants.MAX_MEMBER_AMOUNT_SINGLE_PAGE).build();
            builder.setPage(pageParam);
            ListGroupsByOrgIdRequest request = builder.build();
            ListGroupsByOrgIdResponse response = userGroupServiceBlockingStub.listGroupsByOrgId(request);
            if (response.getStatus().getCodeValue() != Constants.SUCCESS) {
                if (log.isErrorEnabled()) {
                    log.error("查询企业组织层级失败({}):{}", request, response);
                }
                return ServiceResult.fail("查询企业组织层级失败");
            }
            if (CollectionUtil.isEmpty(response.getGroupsList())) {
                if (log.isInfoEnabled()) {
                    log.info("查询企业组织层级结束");
                }
                break;
            }

            List<Group> groups = response.getGroupsList();
            totalCount += groups.size();
            // 分批更新
            Date currentTime = DateUtil.getCommonDate();
            List<MemberUserGroupDO> memberStores = new ArrayList<>(groups.size());
            for (Group group : groups) {
                // 转化
                MemberUserGroupDO memberStore = new MemberUserGroupDO();
                memberStore.setOrgId(orgId);
                memberStore.setGroupId(group.getId());
                List<String> ancestors = new LinkedList<>(group.getParentIdsList());
                ancestors.add(group.getId());
                ancestors = ancestors.stream().sorted().collect(Collectors.toList());
                memberStore.setParentIds(ancestors);
                memberStore.setStatus(group.getStatusValue());
                memberStore.setCreateTime(currentTime);
                memberStore.setUpdateTime(currentTime);
                memberStores.add(memberStore);
            }
            // 批量替换或新增
            memberUserGroupDao.batchInsertReplace(memberStores);
        }
        if (log.isInfoEnabled()) {
            log.info("组织层级同步完成,共计:{}条", totalCount);
        }
        return ServiceResult.success();
    }

    @Override
    public ServiceResult<Boolean> checkUserGroupPermission(String userId, String groupId) {
        ServiceResult<Collection<String>> result = this.checkUserGroupPermissions(userId, Arrays.asList(groupId));
        if (!result.isSuccess()) {
            if (log.isErrorEnabled()) {
                log.error("查询用户组织层级失败({}):{}", userId, result.getMsg());
            }
            return ServiceResult.fail("查询用户组织层级失败");
        }

        return ServiceResult.success(!CollectionUtil.isEmpty(result.getData()));
    }

    @Override
    public ServiceResult<Collection<String>> checkUserGroupPermissions(String userId, Collection<String> uncheckedGroupIds) {
        if (!StringUtils.hasText(userId)) {
            if (log.isErrorEnabled()) {
                log.error("用户id不存在:{}", userId);
            }
            return ServiceResult.fail("用户id不存在");
        }
        // 查询用户组织层级
        ServiceResult<List<Group>> groupResult = this.userStores(userId);
        if (!groupResult.isSuccess()) {
            if (log.isErrorEnabled()) {
                log.error("查询用户组织层级失败({}):{}", userId, groupResult);
            }
            return ServiceResult.fail("查询用户组织层级失败");
        }

        List<MemberUserGroupDO> memberStores = memberUserGroupDao.findByIds(uncheckedGroupIds);
        Map<String, MemberUserGroupDO> memberStoreIds = memberStores.stream()
                .collect(Collectors.toMap(MemberUserGroupDO::getGroupId, Function.identity()));

        List<Group> groups = groupResult.getData();
        Set<String> userStoreIds = groups.stream().map(Group::getId).collect(Collectors.toSet());

        List<String> checkedGroupIds = new ArrayList<>(uncheckedGroupIds.size());
        for (String uncheckedStoreId : uncheckedGroupIds) {
            // id为空
            if (!StringUtils.hasText(uncheckedStoreId)) {
                checkedGroupIds.add(uncheckedStoreId);
                continue;
            }

            // 数据库中不存在、状态异常
            MemberUserGroupDO memberStore = memberStoreIds.get(uncheckedStoreId);
            if (memberStore == null
                    || MemberStoreStatusEnum.ACTIVATED.getIndex() != memberStore.getStatus()) {
                checkedGroupIds.add(uncheckedStoreId);
                continue;
            }

            // 用户具有该权限
            for (String store : memberStore.getParentIds()) {
                if (userStoreIds.contains(store)) {
                    checkedGroupIds.add(uncheckedStoreId);
                    break;
                }
            }
        }

        return ServiceResult.success(checkedGroupIds);
    }

    /**
     * 查询用户组织层级
     *
     * @param userId 用户id
     * @return
     */
    @NotNull
    private ServiceResult<List<Group>> userStores(String userId) {
        ListGroupsByUidRequest request = ListGroupsByUidRequest.newBuilder().setUserId(userId).build();
        ListGroupsByUidResponse response;
        try {
            response = userGroupServiceBlockingStub.listGroupsByUid(request);
        } catch (StatusRuntimeException e) {
            log.error("【联系人】根据 user_id 获取层级组织列表失败，request:{}", request, e);
            return ServiceResult.fail("【联系人】根据 user_id 获取层级组织列表失败");
        }
        if (response.getStatus().getCodeValue() != Constants.SUCCESS) {
            log.error("【联系人】根据 user_id 获取层级组织列表失败，response:{}", response);
            return ServiceResult.fail("【联系人】根据 user_id 获取层级组织列表失败");
        }
        List<Group> groupsList = response.getGroupsList();
        return ServiceResult.success(response.getGroupsList());
    }

    @Override
    public ServiceResult<Collection<String>> checkUserStorePermissions(String userId, Set<String> uncheckedStoreIds) {
        if (!StringUtils.hasText(userId)) {
            if (log.isErrorEnabled()) {
                log.error("用户id不存在:{}", userId);
            }
            return ServiceResult.fail("用户id不存在");
        }
        // 查询用户组织层级
        ServiceResult<List<Group>> groupResult = this.userStores(userId);
        if (!groupResult.isSuccess()) {
            if (log.isErrorEnabled()) {
                log.error("查询用户组织层级失败({}):{}", userId, groupResult);
            }
            return ServiceResult.fail("查询用户组织层级失败");
        }

        List<MemberUserGroupDO> memberStores = memberUserGroupDao.findByIds(uncheckedStoreIds);
        Map<String, MemberUserGroupDO> memberStoreIds = memberStores.stream().collect(Collectors.toMap(MemberUserGroupDO::getGroupId, Function.identity()));

        List<Group> groups = groupResult.getData();
        Set<String> userStoreIds = groups.stream().map(Group::getId).collect(Collectors.toSet());

        List<String> checkedStoreIds = new ArrayList<>(uncheckedStoreIds.size());
        for (String uncheckedStoreId : uncheckedStoreIds) {
            // id为空
            if (!StringUtils.hasText(uncheckedStoreId)) {
                checkedStoreIds.add(uncheckedStoreId);
                continue;
            }

            // 数据库中不存在、状态异常
            MemberUserGroupDO memberStore = memberStoreIds.get(uncheckedStoreId);
            if (memberStore == null
                    || MemberStoreStatusEnum.ACTIVATED.getIndex() != memberStore.getStatus()) {
                checkedStoreIds.add(uncheckedStoreId);
                continue;
            }

            // 用户具有该权限
            for (String store : memberStore.getParentIds()) {
                if (userStoreIds.contains(store)) {
                    checkedStoreIds.add(uncheckedStoreId);
                    break;
                }
            }
        }

        return ServiceResult.success(checkedStoreIds);
    }


    @Override
    public List<String> getGroupIdsByUserIdAndStatus(String orgId, String userId, int status) {
        ServiceResult<List<Group>> result = userStores(userId);
        if (result.isSuccess()) {
            List<Group> data = result.getData();
            if (CollectionUtil.isNotEmpty(data)) {
                List<String> ids = data.stream()
                        .filter(item -> item.getStatus().getNumber() == status)
                        .map(Group::getId)
                        .collect(Collectors.toList());
                if (CollUtil.isNotEmpty(ids)) {
                    List<MemberUserGroupDO> memberStores = memberUserGroupDao.allSubAndInactiveGroup(orgId, ids);
                    if (CollUtil.isNotEmpty(memberStores)) {
                        return memberStores.stream().map(MemberUserGroupDO::getGroupId).collect(Collectors.toList());
                    }
                }
            }
        } else {
            log.error("【member】 getGroupIdsByUserIdAndStatus 失败 {}", result.getMsg());
        }
        return new ArrayList<>();
    }

    @Override
    public List<String> listByParentIn(String store) {
        return memberUserGroupDao.listByParentIn(store);
    }
}
